package com.zhiche.lisa.bms.service.driver.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zhiche.lisa.bms.dao.mapper.driver.PriceconfMileMapper;
import com.zhiche.lisa.bms.dao.model.driver.PriceconfMile;
import com.zhiche.lisa.bms.pojo.vo.driver.PriceconfMileVO;
import com.zhiche.lisa.bms.service.driver.IPriceconfMileService;
import com.zhiche.lisa.bms.utils.ToolCommonUtils;
import com.zhiche.lisa.core.supports.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 线路计价里程 服务实现类
 * </p>
 *
 * @author zhaoguixin
 * @since 2018-08-30
 */
@Service
@Slf4j
public class PriceconfMileServiceImpl extends ServiceImpl<PriceconfMileMapper, PriceconfMile> implements IPriceconfMileService {

    /**
     * 分页查询线路里程
     *
     * @param page
     * @return
     */
    @Override
    public Page<PriceconfMileVO> listByPage(Page<PriceconfMileVO> page) {
        if (Objects.isNull(page)) {
            return null;
        }
        page.setOrderByField("gmt_create");
        page.setAsc(false);
        EntityWrapper<PriceconfMileVO> ew = whereCondition(page);
        List<PriceconfMileVO> list = baseMapper.selectByConditions(page, ew);
        page.setRecords(list);
        return page;
    }

    /**
     * 添加线路价格
     *
     * @param priceconfMileVO
     * @param br
     * @return
     */
    @Override
    public Integer add(PriceconfMileVO priceconfMileVO, BindingResult br) {
        log.info("PriceconfMileServiceImpl.add param : {}", priceconfMileVO);

        if (Objects.isNull(priceconfMileVO)) {
            log.error("PriceconfMileServiceImpl.add param form must not be null");
            throw new BaseException("表单不能为空");
        }
        // 时间格式化
        updateEffectiveAndInvateDate(priceconfMileVO);

        //表单验证
        verificationForm(br);

        //业务验证
        verificationBusiness(priceconfMileVO);


        //查询当前生效的记录，更新失效时间未添加记录的生效时间
        PriceconfMile currentMile = this.selectByEffectiveDateAndRouteId(priceconfMileVO.getRouteId(), priceconfMileVO.getEffectiveDate());
        if (Objects.nonNull(currentMile)) {
            SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-dd");
            String format = sp.format(priceconfMileVO.getEffectiveDate());
            if (format.equals(sp.format(new Date()))) {
                throw new BaseException("修改已存在里程不能选当天日期");
            }
            currentMile.setInvalidDate(priceconfMileVO.getEffectiveDate());
            this.updateById(currentMile);
        }

        PriceconfMile mile = new PriceconfMile();
        BeanUtils.copyProperties(priceconfMileVO, mile);

        this.insert(mile);
        return mile.getId();
    }


    /**
     * 更新线路价格
     *
     * @param priceconfMileVO
     * @param br
     * @return
     */
    @Override
    public Boolean update(PriceconfMileVO priceconfMileVO, BindingResult br) {
        log.info("PriceconfMileServiceImpl.update param : {}", priceconfMileVO);

        if (Objects.isNull(priceconfMileVO)) {
            log.error("PriceconfMileServiceImpl.update param form must not be null");
            throw new IllegalArgumentException("表单不能为空");
        }
        // 时间格式化
        updateEffectiveAndInvateDate(priceconfMileVO);

        //表单验证
        verificationForm(br);

        //业务验证
        verificationBusiness(priceconfMileVO);

        //查询当前生效的记录，更新失效时间未添加记录的生效时间
        PriceconfMile currentMile = this.selectByEffectiveDateAndRouteId(priceconfMileVO.getRouteId(), priceconfMileVO.getEffectiveDate());
        if (Objects.nonNull(currentMile)) {
            currentMile.setInvalidDate(priceconfMileVO.getEffectiveDate());
            this.updateById(currentMile);
        }

        PriceconfMile mile = new PriceconfMile();
        BeanUtils.copyProperties(priceconfMileVO, mile);

        return this.updateById(mile);
    }

    /**
     * 时间格式化
     *
     * @param priceconfMileVO
     */
    private void updateEffectiveAndInvateDate(PriceconfMileVO priceconfMileVO) {
        // 时间格式化
        if (Objects.nonNull(priceconfMileVO.getEffectiveDate())) {
            priceconfMileVO.setEffectiveDate(ToolCommonUtils.getStartOfDate(priceconfMileVO.getEffectiveDate()));
        }
        if (Objects.nonNull(priceconfMileVO.getInvalidDate())) {
            priceconfMileVO.setInvalidDate(ToolCommonUtils.getStartOfDate(priceconfMileVO.getInvalidDate()));
        }
    }

    /**
     * 删除线路信息
     *
     * @param id
     * @return
     * @throws BaseException
     */
    @Override
    public Boolean del(Integer id) throws BaseException {
        log.info("PriceconfMileServiceImpl.del param : {}", id);

        if (Objects.isNull(id) || id.equals(0)) {
            log.error("PriceconfMileServiceImpl.del param id must not be null");
            throw new BaseException("主键不能为空");
        }

        PriceconfMile mile = selectById(id);
        if (Objects.isNull(mile)) {
            log.error("PriceconfMileServiceImpl.del mile is null");
            throw new BaseException("记录不存在");
        }

        Date today = new DateTime().withMillisOfDay(0).toDate();
        if (1 > mile.getEffectiveDate().compareTo(today)) {
            log.error("PriceconfMileServiceImpl.del mile can not delete");
            throw new BaseException("只能删除未生效的记录");
        }

        this.deleteById(id);

        //更新当前记录失效时间为空
        PriceconfMile currentMile = this.selectByEffectiveDateAndRouteId(mile.getRouteId(), new Date());
        if (Objects.nonNull(currentMile)) {
            currentMile.setInvalidDate(null);
            updateById(currentMile);
        }

        return true;
    }

    /**
     * 得到线路计价里程
     *
     * @param id
     * @return
     */
    @Override
    public PriceconfMileVO getById(Integer id) {
        EntityWrapper<PriceconfMileVO> ew = new EntityWrapper<>();
        ew.eq("id", id);
        return baseMapper.getOneByEW(ew);
    }

    /**
     * 构建查询条件
     *
     * @param page
     * @return
     */
    private EntityWrapper<PriceconfMileVO> whereCondition(Page<PriceconfMileVO> page) {
        EntityWrapper<PriceconfMileVO> ew = new EntityWrapper<>();

        //查询条件
        if (Objects.nonNull(page.getCondition())) {
            //起运省
            if (Objects.nonNull(page.getCondition().get("oProvinceCode")) && StringUtils.isNotEmpty(page.getCondition().get("oProvinceCode").toString())) {
                ew.eq("o_province_code", page.getCondition().get("oProvinceCode").toString().trim());
            }

            if (Objects.nonNull(page.getCondition().get("oCityCode")) && StringUtils.isNotEmpty(page.getCondition().get("oCityCode").toString())) {
                ew.eq("o_city_code", page.getCondition().get("oCityCode").toString().trim());
            }

            if (Objects.nonNull(page.getCondition().get("oCountyCode")) && StringUtils.isNotEmpty(page.getCondition().get("oCountyCode").toString())) {
                ew.eq("o_county_code", page.getCondition().get("oCountyCode").toString().trim());
            }

            //起运
            if (Objects.nonNull(page.getCondition().get("oTag")) && StringUtils.isNotEmpty(page.getCondition().get("oTag").toString())) {
                ew.like("o_tag", page.getCondition().get("oTag").toString().trim());
            }

            if (Objects.nonNull(page.getCondition().get("dProvinceCode")) && StringUtils.isNotEmpty(page.getCondition().get("dProvinceCode").toString())) {
                ew.eq("d_province_code", page.getCondition().get("dProvinceCode").toString().trim());
            }

            if (Objects.nonNull(page.getCondition().get("dProvinceCode")) && StringUtils.isNotEmpty(page.getCondition().get("dProvinceCode").toString())) {
                ew.eq("d_province_code", page.getCondition().get("dProvinceCode").toString().trim());
            }

            if (Objects.nonNull(page.getCondition().get("dCityCode")) && StringUtils.isNotEmpty(page.getCondition().get("dCityCode").toString())) {
                ew.eq("d_city_code", page.getCondition().get("dCityCode").toString().trim());
            }

            if (Objects.nonNull(page.getCondition().get("dTag")) && StringUtils.isNotEmpty(page.getCondition().get("dTag").toString())) {
                ew.like("d_tag", page.getCondition().get("dTag").toString().trim());
            }

            if (Objects.nonNull(page.getCondition().get("currentValue")) && StringUtils.isNotEmpty(page.getCondition().get("currentValue").toString())) {
                ew.ge("current_value", page.getCondition().get("currentValue").toString().trim());
            }

            if (Objects.nonNull(page.getCondition().get("effectiveDate")) && StringUtils.isNotEmpty(page.getCondition().get("effectiveDate").toString())) {
                ew.ge("effective_date", page.getCondition().get("effectiveDate").toString().trim());
            }

            if (Objects.nonNull(page.getCondition().get("invalidDate")) && StringUtils.isNotEmpty(page.getCondition().get("invalidDate").toString())) {
                ew.lt("invalid_date", page.getCondition().get("invalidDate").toString().trim());
            }

        }

        return ew;
    }

    /**
     * 判断表单
     *
     * @param br
     */
    private void verificationForm(BindingResult br) {
        if (Objects.isNull(br)) {
            log.error("PriceconfMileServiceImpl.verificationForm error br is null");
            throw new BaseException("BindingResult is null");
        }

        if (br.hasErrors()) {
            List<ObjectError> list = br.getAllErrors();
            log.error("PriceconfMileServiceImpl.verificationForm error : {}", list.get(0).getDefaultMessage());
            throw new BaseException(list.get(0).getDefaultMessage());
        }
    }

    /**
     * 验证是否符合业务需求
     *
     * @param priceconfMileVO
     */
    private void verificationBusiness(PriceconfMileVO priceconfMileVO) {
        log.info("PriceconfMileServiceImpl.verificationBusiness param : {}", priceconfMileVO);

        EntityWrapper<PriceconfMile> ew = new EntityWrapper<>();
        ew.eq("route_id", priceconfMileVO.getRouteId());
        ew.ge("effective_date", priceconfMileVO.getEffectiveDate());
        ew.andNew().le("invalid_date", priceconfMileVO.getEffectiveDate()).or().isNull("invalid_date");
        List<PriceconfMile> list = this.selectList(ew);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        // /**
        //  * 是否已经存在未激活的里程变动
        //  * 激活时间大于
        //  */
        // List<PriceconfMile> collect = list.stream().filter(
        //         o -> -1 < o.getEffectiveDate().compareTo(new DateTime().withMillisOfDay(0).toDate())
        // ).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(list)) {
            if (Objects.nonNull(priceconfMileVO.getId())) {
                if (CollectionUtils.isNotEmpty(list.stream().filter(o -> o.getId() == priceconfMileVO.getId()).collect(Collectors.toList()))) {
                    return;
                }
            }
            if (list.size() >= 1) {
                log.error("PriceconfMileServiceImpl.verificationBusiness already exist not active record");
                throw new BaseException("线路里程已经存在未生效的记录");
            }
            PriceconfMile mile = list.get(0);
            if (Objects.nonNull(priceconfMileVO.getId()) && priceconfMileVO.getId().equals(mile.getId())) {
                return;
            }
            if (priceconfMileVO.getEffectiveDate().compareTo(mile.getEffectiveDate()) > 0) {
                return;
            }

            log.error("PriceconfMileServiceImpl.verificationBusiness already exist not active record");
            throw new BaseException("线路里程已经存在未生效的记录");
        }
    }


    /**
     * 根据线路ID和生效日期查找里程
     *
     * @param routeId
     * @param effectiveDate
     * @return
     */
    @Override
    public PriceconfMile selectByEffectiveDateAndRouteId(Integer routeId, Date effectiveDate) {
        log.info("PriceconfMileServiceImpl.selectByEffectiveDate params : {}, {}", routeId, effectiveDate);

        if (Objects.isNull(effectiveDate)) {
            log.error("PriceconfMileServiceImpl.selectByEffectiveDate param effectiveDate must not be null");
            throw new BaseException("生效时间不能为空");
        }

        EntityWrapper<PriceconfMile> ew = new EntityWrapper<>();
        ew.eq("route_id", routeId)
                .le("effective_date", effectiveDate)
                .and("invalid_date is NULL");
        List<PriceconfMile> list = this.selectList(ew);

        if (CollectionUtils.isEmpty(list)) {
            EntityWrapper<PriceconfMile> ew2 = new EntityWrapper<>();
            ew2.eq("route_id", routeId)
                    .le("effective_date", effectiveDate)
                    .gt("invalid_date", effectiveDate);

            list = this.selectList(ew2);
        }

        if (CollectionUtils.isNotEmpty(list)) {
            return list.get(0);
        }

        return null;
    }


}
